import time
from typing import Optional
import threading


class StreamManager:
    def __init__(self, config_loader):
        self.config_loader = config_loader  # 保存传入的配置加载器对象（ConfigLoader实例），用于后续获取各种配置
        self.config = config_loader.get_app_config()  # 通过配置加载器获取应用主配置（app_config.yaml内容），并保存为字典，方便直接访问各项参数

        # 初始化各个组件
        from src.core.stream_processor import StreamProcessor       # 流处理器
        from src.core.detector import YOLOv8Detector                # 目标检测器
        from src.core.visualizer import Visualizer                  # 可视化器
        from src.services.rtsp_publisher import RTSPPublisher       # RTSP推流器
        from src.services.video_recorder import VideoRecorder       # 视频录制器
        from src.utils.frame_utils import FrameUtils                # 帧工具
        # from src.services.always_recorder import ContinuousVideoRecorder  # 持续录制模块

        # 创建组件实例，参数为 rtsp输入地址和目标帧率
        self.stream_processor = StreamProcessor(
            self.config['rtsp']['input_url'],
            self.config['video']['fps']
        )
        self.detector = YOLOv8Detector(config_loader)          # 创建 yolov8目标检测器
        self.visualizer = Visualizer()                         # 创建可视化器，用于绘制检测结果
        self.publisher = RTSPPublisher(config_loader)          # 创建RTSP推流器
        self.recorder = VideoRecorder(config_loader)           # 创建视频录制器
        self.frame_utils = FrameUtils()                        # 创建帧工具



        # 运行状态
        self.is_running = False     # 流管理器是否运行
        self.main_thread = None     # 主线程，用于启动管理主循环
        self.frame_times = []       # 存储帧时间，用于计算FPS

        # 日志相关
        self.last_log_time = 0          # 上次日志时间
        self.log_interval = 4           # 4秒输出一次日志
        self.frames_pushed = 0          # 推送帧数
        self.current_detections = []    # 当前检测结果

        # 添加Web服务
        # from src.services.web_server import VideoWebServer
        # self.web_server = VideoWebServer(config_loader)
        # Web服务器
        self.web_server = None          # 初始化Web服务器

    def start(self) -> bool:
        """启动流处理管理器"""
        # 启动各个组件
        if not self.stream_processor.start():   # 启动流处理器
            print("无法启动流处理器")
            return False

        if not self.publisher.start():          # 启动RTSP推流服务
            print("无法启动RTSP推流服务")
            return False

        self.is_running = True                                          # 设置流管理器为运行状态
        self.main_thread = threading.Thread(target=self._process_loop)  # 创建主线程，目标为处理循环
        self.main_thread.daemon = True                                  # 设置主线程为守护线程
        self.main_thread.start()                                        # 启动主线程

        # 启动Web服务
        # self.web_server.start()

        # 启动Web服务器
        from src.services.web_server import WebServer           # 导入Web服务器
        self.web_server = WebServer(self.config_loader, self)   # 创建Web服务器实例
        self.web_server.start()                                 # 启动Web服务器

        print("流处理管理器已启动")
        return True  # 返回True，表示流管理器启动成功

    def _process_loop(self):
        """主处理循环：不断从视频流获取帧，进行检测、可视化、推流、录制等操作"""
        while self.is_running:
            try:
                # 获取原始帧【】
                frame = self.stream_processor.get_frame()       # 从流处理器获取最新帧
                if frame is None:                               # 如果帧为空，则等待10毫秒
                    time.sleep(0.01)
                    continue                                    # 继续循环


                # 记录时间用于FPS计算
                current_time = time.time()
                self.frame_times.append(current_time)            # 将当前时间添加到帧时间列表
                if len(self.frame_times) > 100:                  # 如果帧时间列表长度大于100，则删除第一个元素
                    self.frame_times.pop(0)                      # 删除最早的元素

                # 调整帧大小到设定分辨率，保证后续处理一致性，统一调用 frame_utils 的 resize_frame 方法
                frame = self.frame_utils.resize_frame(
                    frame,
                    self.config['video']['frame_width'],
                    self.config['video']['frame_height']
                )
                dispose = self.detector.dispose
                # 进行目标检测，返回检测结果：是否检测到目标、检测到的目标列表、是否存在危险【】
                is_detected, detections, has_danger = self.detector.detect(frame)

                if dispose:
                    # 根据检测状态决定推送的帧(检测到目标+模型加载成功)
                    if is_detected and self.detector.is_initialized:
                        # 检测成功，推送处理后的帧【】
                        annotated_frame = self.visualizer.draw_detections(frame, detections)

                        # 如果检测到危险，触发录制【】
                        if has_danger:
                            self.recorder.trigger_recording()  # 触发录制
                            # TODO: 在这里添加其他警告

                        output_frame = annotated_frame  # 推送处理后的帧
                    else:
                        # 检测未初始化或失败，推送原始帧
                        output_frame = frame
                else:
                    # 检测未初始化或失败，推送原始帧
                    output_frame = frame

                # 添加时间戳和FPS显示（计算FPS）
                # fps = self.frame_utils.calculate_fps(self.frame_times)
                # output_frame = self.frame_utils.add_fps_display(output_frame, fps)

                # 计算物体数量
                object_count = len(detections) if is_detected else 0

                # 添加信息显示（FPS和物体数量）【】
                fps = self.frame_utils.calculate_fps(self.frame_times)
                output_frame = self.frame_utils.add_info_display(output_frame, fps, object_count)

                # 推送帧到RTSP推流器
                self.publisher.push_frame(output_frame)

                # 更新推送帧计数，用于输出日志
                self.frames_pushed += 1

                # 保存当前检测结果
                if is_detected:
                    self.current_detections = detections

                # 定时输出日志
                current_time = time.time()
                if current_time - self.last_log_time >= self.log_interval:
                    self._output_status_log(fps, object_count)
                    self.last_log_time = current_time

                # 添加到录制缓冲（弃用）
                # self.recorder.add_frame(output_frame)

                # 添加到录制缓冲（传入是否有危险的标志）
                self.recorder.add_frame(output_frame, has_danger)   # 添加到缓存


            except Exception as e:
                print(f"处理循环错误: {e}")
                import traceback
                traceback.print_exc()
                time.sleep(0.1)

    def _output_status_log(self, fps: float, object_count: int):
        """输出状态日志"""
        # 构建物体列表
        if self.current_detections:  # 如果当前检测结果不为空
            objects = {}
            for det in self.current_detections:
                cls_name = det['class']                             # 获取检测到的目标的类别
                objects[cls_name] = objects.get(cls_name, 0) + 1    # 统计每个类别的数量

            object_str = ", ".join([f"{name}:{count}" for name, count in objects.items()])  # 将类别和数量拼接成字符串
        else:
            object_str = "无"

        # 状态图标
        detector_status = "✅" if self.detector.is_initialized and self.detector.dispose else "❌"    # 检测器状态
        publisher_status = "✅" if self.publisher.is_running else "❌"      # 推流器状态
        recording_status = "🔴" if self.recorder.is_recording else "⚪"     # 录制器状态

        # 输出日志
        log_msg = (f"[状态] FPS: {fps:.1f} | "
                   f"推送帧数: {self.frames_pushed} | "
                   f"物体: {object_str} | "
                   f"检测器: {detector_status} | "
                   f"推送: {publisher_status} | "
                   f"录制: {recording_status}")

        print(log_msg)

        # 重置推送帧计数
        self.frames_pushed = 0

    def stop(self):
        """停止流处理管理器，关闭所有子模块和线程"""
        self.is_running = False                 # 设置流管理器为停止状态

        if self.main_thread:
            self.main_thread.join(timeout=5)    # 等待主线程结束，最多等待5秒

        # 停止各个组件
        self.stream_processor.stop()            # 停止流处理器
        self.publisher.stop()                   # 停止RTSP推流服务
        # self.always_recorder.stop()  # 停止持续录制

        # # 停止Web服务
        # if hasattr(self, 'web_server'):
        #     self.web_server.stop()

        # 停止Web服务器
        if self.web_server:
            self.web_server.stop()

        print("流处理管理器已停止")
